package cn.rjzjh.tapestry.component;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.internal.services.DocumentLinker;
import org.apache.tapestry5.ioc.Configuration;
import org.apache.tapestry5.ioc.MappedConfiguration;
import org.apache.tapestry5.ioc.OrderedConfiguration;
import org.apache.tapestry5.ioc.Resource;
import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.Contribute;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Primary;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.annotations.Value;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.services.ApplicationDefaults;
import org.apache.tapestry5.ioc.services.Coercion;
import org.apache.tapestry5.ioc.services.CoercionTuple;
import org.apache.tapestry5.ioc.services.FactoryDefaults;
import org.apache.tapestry5.ioc.services.SymbolProvider;
import org.apache.tapestry5.services.AssetFactory;
import org.apache.tapestry5.services.AssetSource;
import org.apache.tapestry5.services.Environment;
import org.apache.tapestry5.services.LibraryMapping;
import org.apache.tapestry5.services.MarkupRenderer;
import org.apache.tapestry5.services.MarkupRendererFilter;
import org.apache.tapestry5.services.RequestGlobals;
import org.apache.tapestry5.services.compatibility.Compatibility;
import org.apache.tapestry5.services.javascript.JavaScriptModuleConfiguration;
import org.apache.tapestry5.services.javascript.JavaScriptStack;
import org.apache.tapestry5.services.javascript.JavaScriptStackSource;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.apache.tapestry5.services.javascript.ModuleManager;
import org.apache.tapestry5.services.javascript.StackExtension;
import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2;
import cn.rjzjh.tapestry.component.services.ISupportedLocales;
import cn.rjzjh.tapestry.component.services.base.PageWorker;
import cn.rjzjh.tapestry.component.services.impl.JqDocLinkerImpl;
import cn.rjzjh.tapestry.component.services.impl.SupportedLocalesImpl;
import cn.rjzjh.tapestry.component.stack.EasyUIStack;

public class LibraryModule {
	public static void bind(ServiceBinder binder) {
		binder.bind(ISupportedLocales.class, SupportedLocalesImpl.class)
				.withId("locales");
	}

	@Contribute(SymbolProvider.class)
	@FactoryDefaults
	public static void contributeFactoryDefaults(
			MappedConfiguration<String, Object> configuration) {
		configuration.add(SymbolConstantsCus.NEED_BOOTSTRAP, false);// 不需要BOOTSTRAP模块
		configuration.add(SymbolConstantsCus.INPUT_WIDTH, 120);// 输入框的默认宽度
		configuration.add(SymbolConstantsCus.PATH_MODULES,
				"classpath:/META-INF/modules");
		configuration.add(SymbolConstantsCus.PATH_EASYUI,
				"classpath:/META-INF/assets/rjzjh/jquery-easyui");
		configuration.add(SymbolConstantsCus.PATH_COMASSETS,
				"classpath:/META-INF/assets/rjzjh");

		configuration.add(SymbolConstantsCus.PATH_JQUERYPLUGIN,
				"classpath:/META-INF/assets/rjzjh/jqueryplugin");

		// configuration.add(SymbolConstantsCus.PATH_ASSETS,
		// "classpath:/rjzjh/tapestry/component/components/assets");
	}

	public static void contributeComponentClassResolver(
			Configuration<LibraryMapping> configuration) {
		configuration.add(new LibraryMapping("rjzjh",
				"cn.rjzjh.tapestry.component"));
	}

	public static void contributeClasspathAssetAliasManager(
			MappedConfiguration<String, String> configuration) {
		configuration.add("tapestry-rjzjh", "META-INF/modules");// 没有它会报：The
																// resource path
																// was not
																// within an
																// aliased path
		configuration.add("tap-jquery", "org/got5/tapestry5");
	}

	@Contribute(JavaScriptStackSource.class)
	public static void addMyStack(
			MappedConfiguration<String, JavaScriptStack> configuration) {
		configuration.addInstance("easyuistack", EasyUIStack.class);
	}

	@Contribute(SymbolProvider.class)
	@ApplicationDefaults
	public static void setupEnvironment(
			MappedConfiguration<String, Object> configuration) {
		configuration.add(SymbolConstants.MINIFICATION_ENABLED, false);
	}

	public static void contributeComponentMessagesSource(
			@Value("/component.properties") Resource componentRes,
			OrderedConfiguration<Resource> configuration) {
		configuration.add("component_properties", componentRes);
	}

	public void contributeMarkupRenderer(
			OrderedConfiguration<MarkupRendererFilter> configuration,
			final ModuleManager moduleManager,
			final Environment environment,
			@Symbol(SymbolConstants.OMIT_GENERATOR_META) final boolean omitGeneratorMeta,
			@Symbol(SymbolConstants.TAPESTRY_VERSION) final String tapestryVersion,
			final RequestGlobals requestGlobals,
			@Symbol(SymbolConstants.CONTEXT_PATH) final String cocntextPath,
			final ISupportedLocales supportedLocales,
			final AssetSource assetSource) {
		MarkupRendererFilter documentLinker = new MarkupRendererFilter() {
			public void renderMarkup(MarkupWriter writer,
					MarkupRenderer renderer) {
				JqDocLinkerImpl linker = new JqDocLinkerImpl(moduleManager,
						omitGeneratorMeta, tapestryVersion, cocntextPath,
						supportedLocales);
				environment.push(DocumentLinker.class, linker);
				renderer.renderMarkup(writer);
				environment.pop(DocumentLinker.class);
				linker.updateDocument(writer.getDocument());
			}
		};
		configuration.override("DocumentLinker", documentLinker);
	}

	@Contribute(ComponentClassTransformWorker2.class)
	@Primary
	public static void addWorker(
			OrderedConfiguration<ComponentClassTransformWorker2> configuration) {
		configuration.addInstance("PageWorker", PageWorker.class,
				"before:Import");// 页面初始化work
	}

	@Contribute(AssetSource.class)
	public void configureStandardAssetFactories(
			MappedConfiguration<String, AssetFactory> configuration) {
		// configuration.add(AssetConstants.CONTEXT, contextAssetFactory);
	}

	@Contribute(ModuleManager.class)
	public static void setupComponentsShims(
			MappedConfiguration<String, Object> configuration,
			@Inject @Path("/META-INF/assets/rjzjh/locale/msg.js") Resource msg,
			@Inject @Path("/META-INF/assets/rjzjh/highcharts/highcharts.js") Resource highcharts_core,
			@Inject @Path("/META-INF/assets/rjzjh/highcharts/modules/exporting.js") Resource highcharts_exporting,
			@Inject @Path("/META-INF/assets/rjzjh/highcharts/modules/export-excel.js") Resource export_excel,
			@Symbol(SymbolConstantsCus.NEED_BOOTSTRAP) boolean needBootstrap) {
		if (!needBootstrap) {// 是否要bootstrap模块
			for (String name : new String[] { "affix", "alert", "button",
					"carousel", "collapse", "dropdown", "modal", "scrollspy",
					"tab", "tooltip", "transition", "popover" }) {
				configuration.override("bootstrap/" + name, null);
			}
			configuration.override("t5/core/typeahead", null);
		}

		configuration.add("msg", new JavaScriptModuleConfiguration(msg));
		/****
		 * highcharts_core highcharts核心模块
		 */
		configuration.add("hcharts", new JavaScriptModuleConfiguration(
				highcharts_core).dependsOn("jquery"));
		configuration.add("hcharts-exp", new JavaScriptModuleConfiguration(
				highcharts_exporting).dependsOn("hcharts"));
		configuration.add("highcharts-excel",
				new JavaScriptModuleConfiguration(export_excel).dependsOn(
						"hcharts", "hcharts-exp"));

	}

	/****
	 * 增加核心js，注意，由于它是无序的，不能把与顺序有关的js放到核心js中，可以采用 work中addHtmlLibrary方式加到页面中
	 */
	@Contribute(JavaScriptStack.class)
	public static void setupCoreJavaScriptStack(
			OrderedConfiguration<StackExtension> configuration,
			Compatibility compatibility,
			@Symbol(SymbolConstantsCus.NEED_BOOTSTRAP) boolean needBootstrap,
			ISupportedLocales supportedLocales,
			JavaScriptSupport javaScriptSupport) {
		if (!needBootstrap) {// 是否需要needBootstrap的样式
			configuration.override("bootstrap.css", null);
		}
		configuration.override("tree.css", null);// 把tapestry默认的树干掉
	}

	/***
	 * 设置默认的转换格式
	 * 
	 * @param configuration
	 */
	/*
	 * public static void contributeValueEncoderSource(
	 * MappedConfiguration<Class, ValueEncoder> configuration) {
	 * configuration.addInstance(List.class, EncoderList.class);//把字符转为List }
	 */
	/****
	 * 组件参数的转换器
	 * 
	 * @param configuration
	 */
	public static void contributeTypeCoercer(
			Configuration<CoercionTuple> configuration) {
		// String以逗号分隔转为List
		Coercion<String, List> coercion = new Coercion<String, List>() {

			@Override
			public List coerce(String input) {
				List<String> retlist = CollectionFactory.newList();
				if (StringUtils.isEmpty(input)) {
					return retlist;
				}
				String[] strs = input.split("\\|");
				for (String str : strs) {
					retlist.add(str);
				}
				return retlist;
			}

		};

		configuration.add(new CoercionTuple<String, List>(String.class,
				List.class, coercion));
	}

	/****
	 * 配置忽略某些路径不让Tapestry5处理，支持Servlet和自定义Filter
	 * 
	 * @param configuration
	 */
	public static void contributeIgnoredPathsFilter(
			Configuration<String> configuration) {
		/*
		 * <servlet> <servlet-name>saveAsImage</servlet-name>
		 * <servlet-class>rjzjh
		 * .tapestry.assembly.httpservlet.SaveAsImage</servlet-class>
		 * <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping>
		 * <servlet-name>saveAsImage</servlet-name>
		 * <url-pattern>/save</url-pattern> </servlet-mapping>
		 */
		configuration.add("/save");// 保存图片调用地址,需要要项目定义相应的servlet
	}

}
